package apibasej.bkp;

import java.io.File;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;

import apibasej.basic.misc.io.UtilFile;
import apibasej.basic.misc.standalone.UtilString;

public class UtilBkpMirror extends UtilBkp {

	public static void main(String[] args) throws Exception {
		
		UtilBkpMirror b = new UtilBkpMirror("Z:\\INSTALADORES", "D:\\INSTALADORES");
		b.startBkp();
		
	}
	
	public static final String FOLDER_LOGS = "_LOGS_BKP_MIRROR";
	
	public UtilBkpMirror(String dirRead, String dirWrite) {
		super(dirRead, dirWrite);
	}


	@SuppressWarnings("static-access")
	@Override
	public void verifyFileSource(File fileSource) throws Exception {
		// cria um arquivo de backup 
		File fileBkp = new File(getDirWrite()+(fileSource.getPath().substring(getDirRead().length())));
		UtilFile uf = new UtilFile();
		
		
		// se existe path igual que um seja arquivo e outro dir deleta do bkp para fazer denovo
		if(fileBkp.exists() && fileSource.isDirectory()!=fileBkp.isDirectory() && !UtilFile.deleteRecursive(fileBkp)) {
			printInfo("[ERROR] COULD NOT DELETE FILE OR DIR: "+fileBkp.getPath());
			ctErros++;
		}
		
		boolean fileBkpExists = fileBkp.exists();
		boolean fileSourceIsDir = fileSource.isDirectory();
		long lastModifiedSource = fileSource.lastModified();
		long sizeFileSource = fileSource.length();
		totalSizeFilesRead += sizeFileSource;
		
		// se não existe ou o tam for diferente ou o lastModified for diferente copia o original
		// se for diretório não confere o tamanho nem o lastModified
		if(!fileBkpExists 
				|| (!fileSourceIsDir && fileBkp.length()!=sizeFileSource) 
				|| (!fileSourceIsDir && fileBkp.lastModified()!=lastModifiedSource) ){
			
			if(fileSourceIsDir){
				fileBkp.mkdirs();
				ctDirsCreateds++;
				printInfo("[NEW_DIR]\t "+fileBkp.getPath());
			}else{
				if(fileBkpExists){
					if(!fileBkp.delete()) {
						printInfo("[ERROR] COULD NOT DELETE FILE BEFORE COPY: "+fileBkp.getPath());
						ctErros++;
					}
				}
				try{
					uf.copyFile(fileSource, fileBkp);
					ctFilesCopieds++;
					totalSizeFilesWrite += sizeFileSource;
					printInfo("[NEW_FILE]\t "+fileBkp.getPath());
				}catch (Exception e) {
					printInfo("[ERROR] ERROR ON COPY FILE: "+fileBkp.getPath(),e);
				}
			}
		}
		fileBkp.setLastModified(lastModifiedSource);// para a data de modificação ficar sempre igual do original
	}
	
	
	private String getRegexRemoveds() throws UnknownHostException, SocketException{
		ArrayList<String> patternsIgnore = new ArrayList<String>();
		patternsIgnore.add("^"+getDirWrite()+"\\\\$RECYCLE.BIN.*");
		patternsIgnore.add("^"+getDirWrite()+"\\RECYCLER.*");
		patternsIgnore.add("^"+getDirWrite()+"\\System Volume Information.*");
		patternsIgnore.add("^"+getDirWrite()+"\\\\"+FOLDER_LOGS+".*");
		return UtilString.genRegex(patternsIgnore,null,true);
	}
	
	@Override
	public void verifyRemoveds() throws Exception {
		UtilFile uf = new UtilFile(){
			@Override
			public void eventAddFile(File f) {
				try {
					// para não apagar os logs
					//if(f.getPath().startsWith(getFileLog().getParent())) return; // colocado no regex
					
					boolean isDir = f.isDirectory();// verifica antes de apagar
					
					File source = new File(getDirRead()+(f.getPath().substring(getDirWrite().length())));
					if(!source.exists()){// se não existe na fonte deleta do local do backup
						boolean del = UtilFile.deleteRecursive(f);
						if(del){
							ctRemoveds++;
							printInfo("[REMOVED]\t "+f.getPath()+"; isDir="+isDir);
						}else{
							ctErros++;
							printInfo("[ERROR] COULD NOT DELETE FILE: "+f.getPath());
						}
					}
				} catch (Exception e) {
					printInfo("[ERROR] ERROR ON VERIFY FILE REMOVED: "+f.getPath(),e);
				}
			}
		};
		uf.setRegexValidFiles(getRegexRemoveds());
		uf.setAddDirs(true);
		uf.readFilesDirs( new File(getDirWrite()).listFiles() );
	}
	
	@Override
	public String getPrefixLog() {
		return FOLDER_LOGS+getFileSeparator();
	}
	private String getFileSeparator(){
		return getDirWrite().substring(getDirWrite().length()-1);
	}
	
	
	@Override
	public void beforeBackup() throws Exception {
		File dirWr = new File(getDirWrite());
		if(!dirWr.exists()) dirWr.mkdirs();
	}
	
	@Override
	public void afterBackup() throws Exception {
	}
	
	
	
}
